package com.geese.module.admin.service.impl;

import com.geese.common.constants.BusinessConstants;
import com.geese.common.constants.Constants;
import com.geese.common.entity.Account;
import com.geese.common.entity.Role;
import com.geese.common.entity.User;
import com.geese.common.entity.UserRole;
import com.geese.common.util.MD5Util;
import com.geese.common.vo.Page;
import com.geese.exception.BusinessException;
import com.geese.module.admin.dto.AdminDTO;
import com.geese.module.admin.service.IAdminService;
import com.geese.module.admin.vo.AdminVO;
import com.geese.module.security.dao.RoleMapper;
import com.geese.module.security.dao.UserRoleMapper;
import com.geese.module.user.dao.AccountMapper;
import com.geese.module.user.dao.UserMapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * Created by huweiwei on 2017/3/29.
 */
@Service
public class AdminServiceImpl implements IAdminService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private AccountMapper accountMapper;
    @Autowired
    private UserRoleMapper userRoleMapper;
    @Autowired
    private RoleMapper roleMapper;

    @Override
    public Map<String, Object> selectList(Page page, AdminVO adminVO) {
        List<User> adminList;
        List<Account> accounts = null;
        if (StringUtils.isEmpty(adminVO.getAccount())) {
            PageHelper.startPage(page.getCurrPage(), page.getPageSize(), " id desc");
            adminList = userMapper.selectAdminList(adminVO);
        } else {
            accounts = accountMapper.findByLikeAccount(adminVO.getAccount());
            List<Integer> userIds = Lists.transform(accounts, new Function<Account, Integer>() {
                @Override
                public Integer apply(Account account) {
                    return account.getUserId();
                }
            });
            PageHelper.startPage(page.getCurrPage(), page.getPageSize(), " id desc");
            adminList = userMapper.selectListByIds(userIds);
        }

        List<Map<String, Object>> data = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(adminList)) {
            if (accounts == null) {
                List<Integer> userIds = Lists.transform(adminList, new Function<User, Integer>() {
                    @Override
                    public Integer apply(User user) {
                        return user.getId();
                    }
                });
                accounts = accountMapper.findByUserIds(userIds);
            }

            Map<Integer, Account> accountMap = Maps.uniqueIndex(accounts, new Function<Account, Integer>() {
                @Override
                public Integer apply(Account account) {
                    return account.getUserId();
                }
            });

            for (User user : adminList) {
                Map<String, Object> temp = Maps.newHashMap();
                Account account = accountMap.get(user.getId());
                temp.put("id", user.getId());
                temp.put("account", account.getAccount());
                temp.put("mobile", user.getMobile());
                temp.put("username", user.getUsername());
                temp.put("department", user.getDepartment());
                temp.put("lastLogin", account.getLastLogin());
                temp.put("lastIp", account.getLastIp());
                temp.put("status", user.getBlock());
                data.add(temp);
            }
        }

        PageInfo pages = new PageInfo(adminList);
        Map<String, Object> pageInfo = Maps.newHashMap();
        pageInfo.put(Constants.CURR_PAGE, pages.getPageNum());
        pageInfo.put(Constants.TOTAL_PAGE, pages.getPages());
        pageInfo.put(Constants.TOTAL, pages.getTotal());

        Map<String, Object> result = Maps.newHashMap();
        result.put(Constants.PAGE_INFO, pageInfo);
        result.put("adminList", data);
        return result;
    }

    @Override
    public void addAdmin(AdminDTO adminDTO) {

        //账号唯一性校验
        String account = adminDTO.getAccount();
        Account accountDO = accountMapper.findByAccount(account);
        if (null != accountDO) {
            throw new BusinessException(120076);
        }

        //新增用户信息
        User user = new User();
        user.setUsername(adminDTO.getUsername());
        user.setMobile(account);
        user.setUserType(BusinessConstants.ADMIN_TYPE);
        user.setDepartment(adminDTO.getDepartment());
        user.setBlock(adminDTO.getBlock());
        user.setEnable(1);
        userMapper.save(user);
        Integer userId = user.getId();
        if (null == userId || userId <= 0) {
            throw new BusinessException(120075);
        }

        //获取用户id,新增账号信息
        accountDO = new Account();
        accountDO.setAccount(account);
        accountDO.setEnable(1);
        accountDO.setBlock(adminDTO.getBlock());
        accountDO.setUserId(userId);
        accountDO.setPassword(MD5Util.encrypt(adminDTO.getPassword()));
        accountDO.setAllowPoint(0);
        accountMapper.save(accountDO);
        Integer accountId = accountDO.getId();
        if (null == accountId || accountId <= 0) {
            throw new BusinessException(120074);
        }

        List<UserRole> insertList = Lists.newArrayList();
        for (Integer roleId : adminDTO.getRoleIds()) {
            UserRole userRole = new UserRole();
            userRole.setEnable(1);
            userRole.setUserId(userId);
            userRole.setRoleId(roleId);
            insertList.add(userRole);
        }
        userRoleMapper.insertBatch(insertList);
    }

    @Override
    public void delete(int id) {
        userMapper.remove(id);
        accountMapper.removeByUserId(id);
        userRoleMapper.removeByUserId(id);
    }

    @Override
    public void deleteBatch(List<Integer> ids) {
        userMapper.removeBatch(ids);
        accountMapper.removeBatchByUserId(ids);
        userRoleMapper.removeBatchByUserId(ids);
    }

    @Override
    public void updateAdmin(AdminDTO adminDTO) {
        Integer userId = adminDTO.getId();
        if (StringUtils.isNotBlank(adminDTO.getPassword())) {
            accountMapper.updatePwd(adminDTO.getId(), MD5Util.encrypt(adminDTO.getPassword()));
        }
        userRoleMapper.removeByUserId(userId);
        if (StringUtils.isNotBlank(adminDTO.getRoleId())) {
            List<Integer> ids = Lists.transform(Arrays.asList(adminDTO.getRoleId().split(",")), new Function<String, Integer>() {
                @Override
                public Integer apply(String s) {
                    return Integer.valueOf(s);
                }
            });
            List<UserRole> userRoles = Lists.newArrayList();
            for (Integer roleId : ids) {
                UserRole userRole = new UserRole();
                userRole.setRoleId(roleId);
                userRole.setUserId(userId);
                userRole.setEnable(1);
                userRoles.add(userRole);
            }
            userRoleMapper.insertBatch(userRoles);
        }
        User user = userMapper.findById(userId);
        user.setUsername(adminDTO.getUsername());
        user.setDepartment(adminDTO.getDepartment());
        user.setBlock(adminDTO.getBlock());
        userMapper.updateById(user);
    }

    @Override
    public Map<String, Object> getDetails(int id) {
        User user = userMapper.findById(id);
        if (user == null) {
            throw new BusinessException(120045);
        }
        Account account = accountMapper.findByUserId(id);
        if (account == null) {
            throw new BusinessException(120119);
        }
        List<Integer> userRoles = userRoleMapper.listByUserId(user.getId());
        List<Role> roleList = roleMapper.getAll();
        List<Map<String, Object>> roles = Lists.newArrayList();
        for (Role role : roleList) {
            Map<String, Object> temp = Maps.newHashMap();
            temp.put("roleId", role.getId());
            temp.put("roleName", role.getDescription());
            if (userRoles.contains(role.getId())) {
                temp.put("checked", 1);
            } else {
                temp.put("checked", 0);
            }
            roles.add(temp);
        }
        Map<String, Object> result = Maps.newHashMap();
        result.put("id", user.getId());
        result.put("account", account.getAccount());
        result.put("department", user.getDepartment());
        result.put("username", user.getUsername());
        result.put("roles", roles);
        result.put("block", user.getBlock());
        return result;
    }
}
